#ifndef _FUNCFILLER_H_
#define _FUNCFILLER_H_

#include "RegularGrid/RectDomain.h"
#include "Core/Tensor.h"

template <int Dim> class FuncFiller;

template <int Dim>
class FuncFiller{
public:
  using iVec = Vec<int,2>;
  using rVec = Vec<Real,2>;
  
  FuncFiller(const RectDomain<Dim>& aDomain);

  template <class TFunc>
  void fillFunc(Tensor<Real,Dim>& res, const TFunc& Func);

protected:
  RectDomain<Dim> Domain;
};

template <int Dim>
FuncFiller<Dim>::FuncFiller(const RectDomain<Dim>& aDomain){
  assert(aDomain.getCentering() == NodeCentered);
  Domain = aDomain;
}

template <>
template <class TFunc>
void FuncFiller<2>::fillFunc(Tensor<Real,2>& res, const TFunc& Func){
  Box<2>& bx = Domain;
  Vec<int,2> lo = bx.lo();
  const Vec<Real,2>& dx = Domain.spacing();
  loop_box_2(bx,i,j){
    iVec Node{i,j};
    rVec rNode = (Node-lo)*dx;
    res(i,j) = Func(rNode);
  }
}

template <>
template <class TFunc>
void FuncFiller<1>::fillFunc(Tensor<Real,1>& res, const TFunc& Func){
  Box<1>& bx = Domain;
  Vec<int,1> lo = bx.lo();
  const Vec<Real,1>& dx = Domain.spacing();
  loop_box_1(bx,i){
    Vec<int,1> Node{i};
    Vec<Real,1> rNode = (Node-lo)*dx;
    res(i) = Func(rNode);
  }
}

#endif //_FUNCFILLER_H_
